package com.commun;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

import maps.test.R;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Typeface;
import android.view.Gravity;
import android.widget.TextView;

import com.activity.MyMapActivity;

public class ArabicUtilities {

	/**
	 * the path of teh fonts file must be under assets folder
	 */
	private static final String FONTS_LOCATION_PATH = "fonts/DejaVuSans.ttf";
	public Map<String, String> ARABIC_LETTERS;
	private static ArabicUtilities instance;

	public static ArabicUtilities getInstance() {
		if (instance == null) {
			instance = new ArabicUtilities();
			instance.InitialiseArabicLetters();
			return instance;
		}
		return instance;
	}

	public static void InitialisationInstance() {

		instance = new ArabicUtilities();
	}

	/**
	 * Helper function is to check if the character passed, is Arabic
	 * 
	 * @param target
	 *            The Character to check Against
	 * @return true if the Character is Arabic letter, otherwise returns false
	 */
	private static boolean isArabicCharacter(char target) {

		// Iterate over the 36 Characters in ARABIC_GLPHIES Matrix
		for (int i = 0; i < ArabicReshaper.ARABIC_GLPHIES.length; i++) {
			// Check if the target Character exist in ARABIC_GLPHIES Matrix
			if (ArabicReshaper.ARABIC_GLPHIES[i][0] == target) {
				return true;
			}
		}

		return false;
	}

	/**
	 * Helper function to split Sentence By Space
	 * 
	 * @param sentence
	 *            the Sentence to Split into Array of Words
	 * @return Array Of words
	 */
	private static String[] getWords(String sentence) {
		if (sentence != null) {
			return sentence.split("\\s");
		} else {
			return new String[0];
		}
	}

	/**
	 * Helper function to check if the word has Arabic Letters
	 * 
	 * @param word
	 *            The to check Against
	 * @return true if the word has Arabic letters, false otherwise
	 */
	public static boolean hasArabicLetters(String word) {

		// Iterate over the word to check all the word's letters
		for (int i = 0; i < word.length(); i++) {

			if (isArabicCharacter(word.charAt(i)))
				return true;
		}
		return false;
	}

	/**
	 * Helper function to check if the word is all Arabic Word
	 * 
	 * @param word
	 *            The word to check against
	 * @return true if the word is Arabic Word, false otherwise
	 */
	public static boolean isArabicWord(String word) {
		// Iterate over the Word
		for (int i = 0; i < word.length(); i++) {
			if (!isArabicCharacter(word.charAt(i)))
				return false;
		}
		return true;
	}

	/**
	 * Helper function to split the Mixed Word into words with only Arabic, and
	 * English Words
	 * 
	 * @param word
	 *            The Mixed Word
	 * @return The Array of the Words of each Word may exist inside that word
	 */
	private static String[] getWordsFromMixedWord(String word) {

		// The return result of words
		ArrayList<String> finalWords = new ArrayList<String>();

		// Temp word to hold the current word
		String tempWord = "";

		// Iterate over the Word Length
		for (int i = 0; i < word.length(); i++) {

			// Check if the Character is Arabic Character
			if (isArabicCharacter(word.charAt(i))) {

				// Check if the tempWord is not empty, and what left in tempWord
				// is not Arabic Word
				if (!tempWord.equals("") && !isArabicWord(tempWord)) {

					// add the Word into the Array
					finalWords.add(tempWord);

					// initiate the tempWord again
					tempWord = "" + word.charAt(i);

				} else {

					// Not to add the tempWord, but to add the character to the
					// rest of the characters
					tempWord += word.charAt(i);
				}

			} else {

				// Check if the tempWord is not empty, and what left in tempWord
				// is Arabic Word
				if (!tempWord.equals("") && isArabicWord(tempWord)) {

					// add the Word into the Array
					finalWords.add(tempWord);

					// initiate the tempWord again
					tempWord = "" + word.charAt(i);

				} else {

					// Not to add the tempWord, but to add the character to the
					// rest of the characters
					tempWord += word.charAt(i);
				}
			}
		}

		String[] theWords = new String[finalWords.size()];
		theWords = finalWords.toArray(theWords);

		return theWords;
	}

	public static String reshape(String allText) {
		if (allText != null) {
			StringBuffer result = new StringBuffer();
			String[] sentences = allText.split("\n");
			for (int i = 0; i < sentences.length; i++) {
				result.append(reshapeSentence(sentences[i]));
				if (sentences.length > 1)
					result.append("\n");
			}
			return result.toString();
		} else {
			return null;
		}

	}

	/**
	 * The Main Reshaping Function to be Used in Android Program
	 * 
	 * @param allText
	 *            The text to be Reshaped
	 * @return the Reshaped Text
	 */
	public static String reshapeSentence(String sentence) {

		// get the Words from the Text
		String[] words = getWords(sentence);

		// prepare the Reshaped Text
		StringBuffer reshapedText = new StringBuffer("");

		// Iterate over the Words
		for (int i = 0; i < words.length; i++) {

			// Check if the Word has Arabic Letters
			if (hasArabicLetters(words[i])) {

				// Check if the Whole word is Arabic
				if (isArabicWord(words[i])) {

					// Initiate the ArabicReshaper functionality
					ArabicReshaper arabicReshaper = new ArabicReshaper(
							words[i], true);

					// Append the Reshaped Arabic Word to the Reshaped Whole
					// Text
					reshapedText.append(arabicReshaper.getReshapedWord());
				} else { // The word has Arabic Letters, but its not an Arabic
					// Word, its a mixed word

					// Extract words from the words (split Arabic, and English)
					String[] mixedWords = getWordsFromMixedWord(words[i]);

					// iterate over mixed Words
					for (int j = 0; j < mixedWords.length; j++) {

						// Initiate the ArabicReshaper functionality
						ArabicReshaper arabicReshaper = new ArabicReshaper(
								mixedWords[j], true);

						// Append the Reshaped Arabic Word to the Reshaped Whole
						// Text
						reshapedText.append(arabicReshaper.getReshapedWord());
					}
				}
			} else {// The word doesn't have any Arabic Letters

				// Just append the word to the whole reshaped Text
				reshapedText.append(words[i]);
			}

			// Append the space to separate between words
			reshapedText.append(" ");
		}

		// return the final reshaped whole text
		return reshapedText.toString();
	}

	public static TextView getArabicEnabledTextView(Context context,
			TextView targetTextView) {
		// this is a static for testing!
		Typeface face = Typeface.createFromAsset(context.getAssets(),
				FONTS_LOCATION_PATH);
		targetTextView.setTypeface(face);
		targetTextView.setGravity(Gravity.RIGHT);
		return targetTextView;
	}

	private String getArabicOrFrenchChars(String nom) {
		String result = "";
		nom = nom.trim();
		int pos = 0;
		while (pos < nom.length()) {
			if (pos < nom.length() - 2) {
				String tmp1 = nom.substring(pos, pos + 2);
				if (tmp1.startsWith("&#")) {
					String key = nom.substring(pos + 2, pos + 6);
					if (ARABIC_LETTERS.containsKey(key)) {
						result += ARABIC_LETTERS.get(key);
						pos += 7;
					} else {
						result += nom.substring(pos, pos + 2);
						pos += 2;
					}
				} else {

					result += nom.charAt(pos);
					pos++;
				}
			} else {

				result += nom.charAt(pos);
				pos++;
			}

		}
		return result.trim();

	}

	// public static List<String> SplitSringInFour(String nom_) {
	// List<String> results = new ArrayList<String>();
	//
	// int pos = 0;
	// while (pos + 4 <= nom_.length()) {
	// if (nom_.charAt(pos) == ' ') {
	// pos++;
	// results.add("0000");
	// }
	// results.add(nom_.substring(pos, pos + 4));
	// pos += 4;
	// }
	// return results;
	// }
	//
	// public String ConcatArabicLetters(List<String> lettersCode) {
	//
	// String result = "";
	// for (String lettCode : lettersCode) {
	//
	// if (ARABIC_LETTERS.containsKey(lettCode))
	//
	// result += ARABIC_LETTERS.get(lettCode);
	// else
	// result += lettersCode;
	// }
	//
	// return result;
	// }

	public String ReshapeInArabicWord(String nom) {
		return getArabicOrFrenchChars(nom);

	}

	public void InitialiseArabicLetters() {

		ARABIC_LETTERS = new HashMap<String, String>();
		Resources res = MyMapActivity.getmContext().getResources();

		ARABIC_LETTERS.put("1569", res.getString(R.string.arab_letter_1));
		ARABIC_LETTERS.put("1570", res.getString(R.string.arab_letter_2));
		ARABIC_LETTERS.put("1571", res.getString(R.string.arab_letter_3));
		ARABIC_LETTERS.put("1572", res.getString(R.string.arab_letter_4));
		ARABIC_LETTERS.put("1573", res.getString(R.string.arab_letter_5));
		ARABIC_LETTERS.put("1574", res.getString(R.string.arab_letter_6));
		ARABIC_LETTERS.put("1575", res.getString(R.string.arab_letter_7));
		ARABIC_LETTERS.put("1576", res.getString(R.string.arab_letter_8));
		ARABIC_LETTERS.put("1577", res.getString(R.string.arab_letter_9));
		ARABIC_LETTERS.put("1578", res.getString(R.string.arab_letter_10));
		ARABIC_LETTERS.put("1579", res.getString(R.string.arab_letter_11));
		ARABIC_LETTERS.put("1580", res.getString(R.string.arab_letter_12));
		ARABIC_LETTERS.put("1581", res.getString(R.string.arab_letter_13));
		ARABIC_LETTERS.put("1582", res.getString(R.string.arab_letter_14));
		ARABIC_LETTERS.put("1583", res.getString(R.string.arab_letter_15));
		ARABIC_LETTERS.put("1584", res.getString(R.string.arab_letter_16));
		ARABIC_LETTERS.put("1585", res.getString(R.string.arab_letter_17));
		ARABIC_LETTERS.put("1586", res.getString(R.string.arab_letter_18));
		ARABIC_LETTERS.put("1587", res.getString(R.string.arab_letter_19));
		ARABIC_LETTERS.put("1588", res.getString(R.string.arab_letter_20));
		ARABIC_LETTERS.put("1589", res.getString(R.string.arab_letter_21));
		ARABIC_LETTERS.put("1590", res.getString(R.string.arab_letter_22));
		ARABIC_LETTERS.put("1591", res.getString(R.string.arab_letter_23));
		ARABIC_LETTERS.put("1592", res.getString(R.string.arab_letter_24));
		ARABIC_LETTERS.put("1593", res.getString(R.string.arab_letter_25));
		ARABIC_LETTERS.put("1594", res.getString(R.string.arab_letter_26));
		ARABIC_LETTERS.put("1601", res.getString(R.string.arab_letter_27));
		ARABIC_LETTERS.put("1602", res.getString(R.string.arab_letter_28));
		ARABIC_LETTERS.put("1603", res.getString(R.string.arab_letter_29));
		ARABIC_LETTERS.put("1604", res.getString(R.string.arab_letter_30));
		ARABIC_LETTERS.put("1605", res.getString(R.string.arab_letter_31));
		ARABIC_LETTERS.put("1606", res.getString(R.string.arab_letter_32));
		ARABIC_LETTERS.put("1607", res.getString(R.string.arab_letter_33));
		ARABIC_LETTERS.put("1608", res.getString(R.string.arab_letter_34));
		ARABIC_LETTERS.put("1609", res.getString(R.string.arab_letter_35));
		ARABIC_LETTERS.put("1610", res.getString(R.string.arab_letter_36));
		// special caracters
		ARABIC_LETTERS.put("1600", res.getString(R.string.arab_letter_37));

	}

}